package com.Renderer;

import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;

import com.Core.GameAnimation;
import com.Core.GameEngine;

public class ObjectTextureLoader
{	private Bitmap objTexture;
	private FloatBuffer textureBuffer,vertexBuffer;
	private ByteBuffer indexBuffer;
	private int[] textures = new int[1];
	private float vertices[]=
	{	0.0f, 0.0f,	0.0f,
		1.0f, 0.0f, 0.0f,
		1.0f, 1.0f, 0.0f,
		0.0f, 1.0f, 0.0f
	};
	private float texture[]=
	{	0.0f,						0.0f,
		GameEngine.TEXTURE_UNIT,	0.0f,
		GameEngine.TEXTURE_UNIT,	GameEngine.TEXTURE_UNIT,
		0.0f,						GameEngine.TEXTURE_UNIT
	};
	private byte indices[]=
	{	0,1,2,
		0,2,3
	};

	public ObjectTextureLoader()
	{	vertexBuffer = PrepareBuffer(vertices);
		textureBuffer= PrepareBuffer(texture);
		
		indexBuffer = ByteBuffer.allocateDirect(indices.length); 
		indexBuffer.put(indices);
		indexBuffer.position(0);
	}
	private FloatBuffer PrepareBuffer(float[] vArray)
	{	ByteBuffer byteBuf = ByteBuffer.allocateDirect(vArray.length*4);
		byteBuf.order(ByteOrder.nativeOrder());
		FloatBuffer buf = byteBuf.asFloatBuffer();
		buf.put(vArray);buf.position(0);
		return buf;
	}
	public void loadTexture(GL10 gl, Context context)
	{	InputStream imagestream = null;
		try
		{	imagestream 	= context.getResources().openRawResource(GameEngine.GAME_OBJ_TEXTURE);
			objTexture		= BitmapFactory.decodeStream(imagestream);
		}
		catch (Exception e)
		{}
		finally
		{	try
			{	imagestream.close();
				imagestream=null;
			}
			catch (IOException e)
			{}
		}
		
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
	
		gl.glGenTextures(1, textures, 0);
		
//		gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
//		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, objTexture, 0);
		ByteBuffer bb = extract(objTexture); 
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
		gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA,objTexture.getWidth(), objTexture.getHeight(), 0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bb);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); 
		
		objTexture.recycle();
	}
	private void draw(GL10 gl)
	{	gl.glFrontFace(GL10.GL_CCW);
		gl.glEnable(GL10.GL_CULL_FACE);
		gl.glCullFace(GL10.GL_BACK);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
		gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, GL10.GL_UNSIGNED_BYTE, indexBuffer);
		
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glDisable(GL10.GL_CULL_FACE);
	}
	public void DrawAtCell(GL10 gl, int row, int col, int texRow, int texCol, boolean scaleAni)
	{	gl.glMatrixMode(GL10.GL_TEXTURE);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glTranslatef(texRow*GameEngine.TEXTURE_UNIT, texCol*GameEngine.TEXTURE_UNIT, 0);
		
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		if (scaleAni)
		{	if (!GameEngine.disableInput)
			{	float ratio=GameAnimation.getScaleRatio(),ivr=1.0f-ratio;
				gl.glTranslatef(row+ivr/2, col+ivr/2, 0);
				gl.glScalef(ratio, ratio, 1);
			}
			else
			{	if (GameEngine.tracker.isPosAvail())
				{	float dX=(float)(GameEngine.tracker.curX-row)*GameEngine.logic.transPhase/GameAnimation.transPhases;
					float dY=(float)(GameEngine.tracker.curY-col)*GameEngine.logic.transPhase/GameAnimation.transPhases;
					gl.glTranslatef(dX, dY, 0);
				}
				gl.glTranslatef(row, col, 0);
			}
		}
		else
			gl.glTranslatef(row, col, 0);
		
		draw(gl);
		gl.glMatrixMode(GL10.GL_TEXTURE);gl.glPopMatrix();
		gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glPopMatrix();
	}
	public void DrawAtPos(GL10 gl, float x, float y, int texRow, int texCol,float scaleRatio)
	{	gl.glMatrixMode(GL10.GL_TEXTURE);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glTranslatef(texRow*GameEngine.TEXTURE_UNIT, texCol*GameEngine.TEXTURE_UNIT, 0);
		
		gl.glMatrixMode(GL10.GL_MODELVIEW);
		gl.glPushMatrix();
		gl.glLoadIdentity();
		gl.glTranslatef(x-GameEngine.CELL_LENGTH/2, y-GameEngine.CELL_LENGTH/2, 0);
		gl.glScalef(scaleRatio, scaleRatio, 1.0f);
		
		draw(gl);
		gl.glMatrixMode(GL10.GL_TEXTURE);gl.glPopMatrix();
		gl.glMatrixMode(GL10.GL_MODELVIEW);gl.glPopMatrix();
	}
	
	private static ByteBuffer extract(Bitmap bmp)
	{
		ByteBuffer bb = ByteBuffer.allocateDirect(bmp.getHeight() * bmp.getWidth() * 4);
//		bb.order(ByteOrder.BIG_ENDIAN);
		IntBuffer ib = bb.asIntBuffer();
		// Convert ARGB -> RGBA
		for (int y = bmp.getHeight() - 1; y > -1; y--)
		{

			for (int x = 0; x < bmp.getWidth(); x++)
			{
				int pix = bmp.getPixel(x, bmp.getHeight() - y - 1);
				int alpha = ((pix >> 24) & 0xFF);
				int red = ((pix >> 16) & 0xFF);
				int green = ((pix >> 8) & 0xFF);
				int blue = ((pix) & 0xFF);

				// Make up alpha for interesting effect

				//ib.put(red << 24 | green << 16 | blue << 8 | ((red + blue + green) / 3));
				ib.put(red << 24 | green << 16 | blue << 8 | alpha);
			}
		}
		bb.position(0);
		return bb;
	}
}
